home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / borland / jnfb88.zip / EXPWLD.ZIP / WILD.C < prev   
C/C++ Source or Header  |  1987-08-18  |  7KB  |  190 lines

  1. #include <stdio.h>
  2. #include <dir.h>            /* The stuff for fnsplit and ffblk */
  3.  
  4. /* We use a far pointer for the source so that no matter what 
  5.    memory model you use the DOS command line can be passed to 
  6.    expwild.  Because the command line resides outside of Turbo 
  7.    C's data segment, it must be passed this way.  We do not want 
  8.    the routine wild() to have to deal with far pointers, however.  
  9.    To avoid this problem we copy any file specification we are 
  10.    about to pass to wild() into a local variable.  */
  11.  
  12.  
  13. expwild (source, dest, maxsize)    /* called from setargv to */
  14.                                    /* handle any wildcard */
  15.                                    /* specifications in the */ 
  16.                                    /* command line */
  17.  
  18. char far *source;       
  19. char *dest;
  20. int maxsize;
  21.  
  22.   int count = 1, savecount = 1, wildcount;
  23.   char *dwrdptr,                /* destination string pointer */
  24.        wildspec[128],           /* 128 is max command line size */
  25.        *wildptr;                /* used to extract wildcard spec */
  26.   char far *swrdptr;            /* Far pointer to match source */
  27.  
  28.   swrdptr = source;             /* Initialize the source and */
  29.   dwrdptr = dest;               /* destination word pointers */
  30.  
  31. /* Move characters from the source to the destination until
  32.    we hit the end of the null-terminated string. */
  33.     
  34.   while ((*dest = *source++) != '\0') 
  35.   {
  36.  
  37. /* If the string is too big, we're done.  Exit the loop. */
  38.  
  39.     if (++count >= maxsize) break;
  40.  
  41. /* Possibly take some action based on what the character was */
  42.  
  43.     switch (*dest++)
  44.     {
  45.       case '*':
  46.       case '?':
  47.  
  48. /* We just moved a wildcard character.  Move back in the source to 
  49.    the start of the last word and copy into wildspec (our local 
  50.    variable buffer for the call to wild) that word.  In this way 
  51.    wild need not deal with a far pointer.  We copy until we hit a 
  52.    space, tab or the end of the string.  Terminate the wildcard 
  53.    specification string with a null.  Reset count to what it was 
  54.    at the start of the word. */
  55.  
  56.         wildptr = wildspec;
  57.         source = swrdptr;
  58.         while ( *source != ' ' && *source != '\t' &&
  59.                 *source != '\0' ) *wildptr++ = *source++;
  60.         *wildptr = '\0';
  61.         count = savecount;
  62.  
  63. /* Call wild to expand the wild spec.  Put the answer where the
  64.    last destination word pointer was.  Update the count and the
  65.    destination pointer. */
  66.  
  67.         wildcount = wild (wildspec, dwrdptr, maxsize - count);
  68.         count += wildcount;
  69.         dest = dwrdptr + wildcount;
  70.         break;
  71.  
  72. /* dest now contains any previous arguments plus this one that
  73.    has been expanded by wild().  We're done with this case. */
  74.  
  75.       case ' ':
  76.       case '\t':
  77.  
  78. /* We hit a word terminator.  We update the source and 
  79.    destination word pointers to point to the next character.  
  80.    We also save the count as of the start of this word, in case  
  81.    we have to roll back to this position later. */
  82.    
  83.         swrdptr = source;
  84.         dwrdptr = dest;
  85.         savecount = count;
  86.         break;
  87.  
  88. /* Don't do anything for any other character.  Just move it from 
  89.    the source string to the destination string.  */
  90.  
  91.       default:
  92.         break;
  93.  
  94.     }  /* switch */
  95.  
  96.   }  /* while loop */
  97.  
  98.   return (count);                 /* Return the length of the new */
  99.                                   /* command line */
  100. }  /* expwild */
  101.  
  102.  
  103. int wild (wildspec, expand, maxsize)   /* general purpose routine */
  104.                                        /* that accepts an input */
  105.                                        /* wildcard spec wildspec */
  106.                                        /* and puts the resulting */
  107.                                        /* full file names, if any, */
  108.                                        /* in expand */
  109.  
  110. char *wildspec, *expand;
  111. int maxsize;
  112.  
  113. {
  114.   struct ffblk ffblk;           /* Special file block */
  115.   char drive[MAXDRIVE], dir[MAXDIR], name[MAXFILE], ext[MAXEXT];
  116.                                 /* these constants are in dir.h */
  117.                                 /* and reflect DOS size limits */
  118.   char *bufptr;
  119.   int size = 0;
  120.  
  121.   bufptr = expand;              /* Save our original pointer */
  122.  
  123. /* Split the file name into its fundamental components. We need 
  124.    the drive and directory information because the findfirst and 
  125.    findnext functions return only simple file names, and we want 
  126.    to return to our caller complete, unambiguous file pathnames. */
  127.     
  128.   fnsplit (wildspec, drive, dir, name, ext);
  129.  
  130. /* Find the first file that matches the input wildcard specification.
  131.    If none match, then copy the input string to the output output 
  132.    string and return the length of the resulting string. Note that 
  133.    another option is to return a null if the caller passes in a 
  134.    wildcard spec that matches no file.  We elected to let the caller 
  135.    handle the results in this case.  Both findfirst and findnext 
  136.    require a special file information block structure of type 
  137.    ffblk. */
  138.     
  139.   if (findfirst (wildspec, &ffblk, 0) != 0)
  140.   {
  141.     strncpy (expand, wildspec, maxsize);
  142.     return (strlen (expand));
  143.   } /* if no files match this wildcard specification */
  144.  
  145.   while (1)  /* loop until no more files match the wildcard spec */
  146.   {
  147.  
  148. /* Build up the complete file name from the optional drive name
  149.    and path name of the original wild file spec and the file name
  150.    found by either findfirst or findnext.  maxsize-size is always 
  151.    the total space remaining for the string.  */
  152.  
  153.     strncpy (bufptr, drive, maxsize - size);
  154.     strncat (bufptr, dir, maxsize - size);
  155.     strncat (bufptr, ffblk.ff_name, maxsize - size);
  156.  
  157.     size += strlen (bufptr);     /* Increase the string size to */
  158.                                  /* reflect the added file name */
  159.  
  160. /* If the string is now too long, roll back to the previous 
  161.    file name, deposit a null and return the string size.  bufptr 
  162.    still points to the start of this new file name, so rolling 
  163.    back is simple.  */
  164.  
  165.     if (size >= maxsize - 1)
  166.     {
  167.       *(bufptr - 1) = '\0';
  168.       return (strlen (expand));
  169.     } /* if the string is too long */
  170.  
  171. /* Update the pointer to move past the newly added file name and 
  172.    put a space after that file name.  Because we compared size to 
  173.    maxsize-1 above, we know there is room for the blank. */
  174.         
  175.     bufptr = expand + size++;
  176.     *bufptr++ = ' ';
  177.  
  178. /* Get the next file.  If there are no more, back up and put
  179.    a null over the space after the last name and return the size. */
  180.         
  181.     if (findnext (&ffblk) != 0)
  182.     {
  183.       *(bufptr - 1) = '\0';
  184.       return (size);
  185.     }  /* if there are no more files that match this spec */
  186.  
  187.   }  /* loop through all matching file names */
  188. }  /* wild */
  189.